package com.bestv.search.management.command;

import com.bestv.search.common.dataSource.DataSourceKey;
import com.bestv.search.common.dataSource.DataSourceKeyUtil;
import com.bestv.search.common.model.SysUser;
import com.bestv.search.common.model.UserStatusSummary;
import com.bestv.search.common.service.UserStatusManager;
import com.bestv.search.common.util.Excel;
import com.bestv.search.common.util.ExcelSheet;
import org.apache.log4j.Logger;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.jfree.data.category.DefaultCategoryDataset;
import org.jfree.data.general.Dataset;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author Justin Luo
 */
public class UserStatusCommand {

    private static final String NEW_USER_COUNT_LABEL = "用户";
    private static final String NEW_USER_COUNT_SHEET_NAME = "新增用户数";
    private static final String USER_STATUS_COUNT_SHEET_NAME = "用户状态统计";
    private static final String ACTIVE_USER_LABEL = "活跃用户";
    private static final String NORMAL_USER_LABEL = "一般用户";

    private Logger logger = Logger.getLogger(UserStatusCommand.class);

    private UserStatusManager userStatusManager;

    public void updateUserStatus(String siteCode) {

        logger.info("Update user status started. ");

        DataSourceKey key = DataSourceKeyUtil.convert(siteCode);
        userStatusManager.updateUserStatus(key);

        logger.info("Update user status started finished.");
    }

    public Map<String, Dataset> getChartDatasetAndToolTipIdForNewUserCount(SysUser user,
                                                                           Map<String, String[]> parameterMap, DataSourceKey dsKey) {
        String toolTipId = "chartToolTipMap";
        String[] startDate = parameterMap.get("monthFrom");
        String[] endDate = parameterMap.get("monthTo");

        // Gets new user amount
        List<String[]> list = userStatusManager.getNewUserAmountByMonth(dsKey, startDate[0], endDate[0]);
        Dataset dataset = new DefaultCategoryDataset();
        for (String[] row : list) {
            ((DefaultCategoryDataset) dataset).addValue(Long.valueOf(row[1]), NEW_USER_COUNT_LABEL, row[0]);
        }

        // return toolTipId and dataset.
        Map<String, Dataset> result = new HashMap<String, Dataset>();
        result.put(toolTipId, dataset);
        return result;
    }

    public Map<String, Dataset> getChartDatasetAndToolTipIdForUserStatusCount(SysUser user,
                                                                              Map<String, String[]> parameterMap, DataSourceKey dsKey) {
        String toolTipId = "chartToolTipMap";
        String[] startDate = parameterMap.get("dateFrom");
        String[] endDate = parameterMap.get("dateTo");

        // Gets user status infos
        List<UserStatusSummary> list = userStatusManager.getUserStatusOfSummary(dsKey, convert(startDate[0]),
                convert(endDate[0]));

        Dataset dataset = new DefaultCategoryDataset();
        SimpleDateFormat xAxisLabelFormat = new SimpleDateFormat("yyyy-MM-dd");
        for (UserStatusSummary statusSum : list) {
            String rowKey = "";
            if (statusSum.getStatus() == 1) {
                rowKey = NORMAL_USER_LABEL;
            } else if (statusSum.getStatus() == 2) {
                rowKey = ACTIVE_USER_LABEL;
            } else {
                logger.error("Unknow info found for status: " + statusSum.getStatus());
            }
            ((DefaultCategoryDataset) dataset).addValue(statusSum.getAmount(), rowKey,
                    xAxisLabelFormat.format(statusSum.getDate()));
        }

        // return toolTipId and dataset.
        Map<String, Dataset> result = new HashMap<String, Dataset>();
        result.put(toolTipId, dataset);
        return result;
    }

    public HSSFWorkbook createExcelForNewUser(SysUser user, Map<String, String[]> map, DataSourceKey dsKey) {
        String[] startDate = map.get("monthFrom");
        String[] endDate = map.get("monthTo");

        // Gets new user amount
        List<String[]> list = userStatusManager.getNewUserAmountByMonth(dsKey, startDate[0], endDate[0]);

        String sheetName = NEW_USER_COUNT_SHEET_NAME;
        Excel excel = new Excel();

        // Ccreate sheet
        ExcelSheet sheet = new ExcelSheet();
        sheet.setSheetName(sheetName);

        // Create headers
        List<String> headers = new ArrayList<String>();
        headers.add("月份");
        headers.add("用户数量");
        sheet.setDataHeader(headers);

        // Creates data
        sheet.setData(list);

        HSSFWorkbook book = excel.create(sheet);
        return book;
    }

    public HSSFWorkbook createExcelForUserStatus(SysUser user, Map<String, String[]> map, DataSourceKey dsKey) {
        String[] startDate = map.get("dateFrom");
        String[] endDate = map.get("dateTo");

        // Gets user status infos
        List<UserStatusSummary> list = userStatusManager.getUserStatusOfSummary(dsKey, convert(startDate[0]),
                convert(endDate[0]));

        String sheetName = USER_STATUS_COUNT_SHEET_NAME;
        Excel excel = new Excel();

        // Ccreate sheet
        ExcelSheet sheet = new ExcelSheet();
        sheet.setSheetName(sheetName);

        // Create headers
        List<String> headers = new ArrayList<String>();
        headers.add("日期");
        headers.add("状态");
        headers.add("数量");
        sheet.setDataHeader(headers);

        // Creates data
        List<String[]> data = new ArrayList<String[]>();
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        for (UserStatusSummary summary : list) {
            String[] row = new String[3];
            row[0] = format.format(summary.getDate());
            row[1] = summary.getStatus() == 1 ? NORMAL_USER_LABEL : ACTIVE_USER_LABEL;
            row[2] = String.valueOf(summary.getAmount());
            data.add(row);
        }
        sheet.setData(data);

        HSSFWorkbook book = excel.create(sheet);
        return book;
    }

    // Converts date string to date object
    private Date convert(String date) {
        Calendar c = null;
        String format = "(\\d{4})-(\\d{2})-?(\\d{0,2})";
        Pattern pattern = Pattern.compile(format);
        Matcher matcher = pattern.matcher(date);
        if (matcher.matches()) {
            c = Calendar.getInstance();
            int year = Integer.parseInt(matcher.group(1));
            int month = Integer.parseInt(matcher.group(2)) - 1;

            // If convert month(etc.2012-10) to date object, set values of day
            // to "01"
            int day = Integer.parseInt(matcher.group(3).equals("") ? "01" : matcher.group(3));
            c.set(year, month, day, 0, 0, 0);
            c.set(Calendar.MILLISECOND, 0);
        } else {
            logger.error("Date format is not correctly.");
        }
        return c.getTime();
    }

    public UserStatusManager getUserStatusManager() {
        return userStatusManager;
    }

    public void setUserStatusManager(UserStatusManager userStatusManager) {
        this.userStatusManager = userStatusManager;
    }
}